/*
 * MemorySelector.java
 * 
 * last update: 16.01.2010 by Stefan Saru
 * 
 * author:	Alec(panovici@elcom.pub.ro)
 * 
 * Obs:
 */
package engine;

import java.util.*;
/**
 * Selects a word from ammemory. The 'address'
 * is computed at runtime.
 */
//FIXME: the adress is declared as long, so here we
//have a 32 bits limitation
class MemorySelector extends Expression implements LeftValue, Monitor{

	Register mem;
	Expression address;
	GenericSelectorDescription desc; //runtime type info
	Vector monitors;
	int lastAddress;
	boolean isSigned;
	LocationValueChangeMonitor valMonitor;

	/**
	 * true if the address is a defined value
	 * i.e. no X'es or Z's
	 */
	boolean validAddress;

	public MemorySelector(NameSpace n, Register mem,
			GenericSelectorDescription desc,
			Expression address, boolean isSigned)
	{
		super(n);
		this.mem = mem;
		this.desc = desc;
		length = mem.getData(0).n;
		this.address = address;
		monitors = new Vector();
		address.addMonitor(this);
		validAddress = false;
		this.isSigned = isSigned;
		valMonitor = new LocationValueChangeMonitor();
	}

	public void addMonitor(Monitor m){
		monitors.add(m);
	}

	public void trigger() throws InterpretTimeException {
		boolean valid = true;
		int intAddress = 0;
		long longAddress = 0;
		try {
			intAddress = (int) (longAddress = address.evaluate().getInt().value());
		} catch (UndefinedValueException uvex) {
			valid = false ;
		}

		if (intAddress != longAddress)
			xConsole.warn(this + ": adress value exceedes int domain: truncated");

		if ((valid != validAddress) || (valid && validAddress)) {

			lastAddress = intAddress;
			notifyMonitors();
		}
	}

	void notifyMonitors() throws InterpretTimeException
	{
		for (Enumeration e = monitors.elements() ; e.hasMoreElements(); )
			((Monitor)e.nextElement()).trigger();
	}

	public void assign(Result result) throws InterpretTimeException
	{
		BitVector val = isSigned ? result.getInt() : result.getBits();
		if(length > val.n ) val.expandS(length);
		if(length < val.n ) val.trunc(length);

		if (validAddress) {
			mem.getData(lastAddress).attrib(val);
		} else
			xConsole.warn("assgnement to an undefined mem location: ignored");
	}

	public Result evaluate()
	{
		if (!validAddress)
			return BitVector.bX();
		return new BitVector(mem.getData(lastAddress));
	}

	public String toString(){
		return desc.toString();
	}

	public int length() {
		return length;
	}

	class LocationValueChangeMonitor implements Monitor{
		BitVector oldValue;

		public void trigger() {

		}
	}
}

